home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Windows Undocumented File Formats
/
Windows Undocumented File Formats.img
/
CHAP6
/
DECOMP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1997-07-15
|
5KB
|
185 lines
/**********************************************************************
*
* PROGRAM: DECOMP.C
*
* PURPOSE: Decompress a file compressed with Microsoft's COMPRESS.EXE utility.
* Functionally equivalent to EXPAND.EXE.
*
* Copyright 1997, Mike Wallace and Pete Davis
*
* Chapter 6, Compression Algorithm and File Formats, from Undocumented Windows
* File Formats, published by R&D Books, an imprint of Miller Freeman, Inc.
*
**********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "decomp.h"
#define WINSIZE 4096
#define LENGTH(x) ((((x) & 0x0F)) + 3)
#define OFFSET(x1, x2) ((((((x2 & 0xF0) >> 4) * 0x0100) + x1) & 0x0FFF) \
+ 0x0010)
#define FAKE2REAL_POS(x) ((x) & (WINSIZE - 1))
#define BITSET(byte, bit) (((byte) & (1<<bit)) > 0)
/* This is our Compression Window */
char Window[WINSIZE];
/*************************************************
Decides how many bytes to read, depending on the
number of bits set in the Bitmap
**************************************************/
int BytesToRead(unsigned char BitMap) {
int TempSum, counter, c;
TempSum = 8;
for (counter = 0; counter < 8; counter ++) {
c = BITSET(BitMap, counter);
TempSum += (1 - BITSET(BitMap, counter));
}
return TempSum;
} /* BytesToRead - end */
/*************************************************
Decompresses the data using Microsoft's LZ77
derivative.
**************************************************/
void Decompress(FILE *infile, FILE *outfile, long CompSize) {
unsigned char BitMap, byte1, byte2;
int Length, counter;
long Offset, CurrPos=0;
for (counter = 0; counter < WINSIZE; counter ++)
Window[counter] = ' ';
/* Go through until we're done */
while (CurrPos < CompSize) {
/* Get BitMap and data following it */
BitMap = fgetc(infile);
if (feof(infile)) return;
(void) BytesToRead(BitMap);
/* Go through and decode data */
for (counter = 0; counter < 8; counter++) {
/* It's a code, so decode it and copy the data */
if (!BITSET(BitMap, counter)) {
byte1 = fgetc(infile);
if (feof(infile)) return;
byte2 = fgetc(infile);
Length = LENGTH(byte2);
Offset = OFFSET(byte1, byte2);
/* Copy data from 'window' */
while (Length) {
byte1 = Window[FAKE2REAL_POS(Offset)];
Window[FAKE2REAL_POS(CurrPos)] = byte1;
fputc(byte1, outfile);
CurrPos++;
Offset++;
Length--;
}
}/* if */
else {
byte1 = fgetc(infile);
Window[FAKE2REAL_POS(CurrPos)] = byte1;
fputc(byte1, outfile);
CurrPos++;
}
if (feof(infile)) return;
} /* for */
} /* while */
} /* Decompress - end */
/***************************************************
Read the header at the beginning of the compressed
file and verity it is a valid input file.
****************************************************/
void ReadHeader(FILE *infile, FILE *outfile) {
COMPHEADER CompHeader;
long CompSize;
fseek(infile, 0, SEEK_END);
CompSize = ftell(infile);
fseek(infile, 0, SEEK_SET);
fread(&CompHeader, sizeof(CompHeader), 1, infile);
if ((CompHeader.Magic1 != MAGIC1) || (CompHeader.Magic2 != MAGIC2)) {
printf("Fatal Error:\n");
printf(" Not a valid Compressed file file!\n");
return;
}
printf("Decompressing file from %lu bytes to %lu bytes\n",
CompSize, CompHeader.DecompSize);
Decompress(infile, outfile, CompHeader.DecompSize);
printf("Done!\n");
} /* ReadHeader - end */
/***************************************************
Show usage.
****************************************************/
void Usage( void ) {
printf("Usage:\n");
printf(" DECOMP file1.ext file2.ext\n\n");
printf(" file1.ext - Name of compressed file\n");
printf(" file2.ext - Name of decompressed file\n\n");
} /* Usage - end */
/***************************************************
Open the file and dump it.
****************************************************/
int main(int argc, char *argv[]) {
char filename[128];
FILE *infile, *outfile;
if (argc < 3) {
Usage();
return EXIT_FAILURE;
}
strcpy(filename, argv[1]);
if ((infile = fopen(filename, "rb")) == NULL) {
printf("%s does not exist!", filename);
return EXIT_FAILURE;
}
strcpy(filename, argv[2]);
if ((outfile=fopen(filename, "wb")) == NULL) {
printf("Error opening destination file!");
return(EXIT_FAILURE);
}
ReadHeader(infile, outfile);
fclose(infile);
fclose(outfile);
return(EXIT_SUCCESS);
} /* main - end */
/* decomp.c - end */